#pragma once
#include <iostream>
#include <string>
#include <queue>
#include <pthread.h>
const static int defaultcap =5;



template<typename T>
class BlockQueue
{
private:

    bool IsFull()
    {
        return _block_queue.size() == _max_cap;
    }

    bool IsEmpty()
    {
        return _block_queue.empty();

    }

public:
    BlockQueue(int cap =defaultcap):_cap(cap)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_p_cond,nullptr);
        pthread_cond_init(&_c_cond,nullptr);
    }

    void Pop(T* out)
    {
        pthread_mutex_lock(&_mutex);
        while(IsEmpty())
        {
            //添加尚未满足，但是线程被异常唤醒的情况，叫做伪唤醒！

            pthread_cond_wait(&_c_cond,&_mutex);
        }
        //1.没有满 ||2.被唤醒了
        *out = _block_queue.front();
        _block_queue.pop();

        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_p_cond);
    }

    //一个生产者
    void Equeue(const T &in)
    {
        pthread_mutex_lock(&_mutex);
        while(IsFull())//if?
        {
            //满了，生产者不能生产，必须等待
            //可是在临界区里面呀!!
            //被调用的时候：除了让自己继续排队等待，还会自己释放传入的锁
            //函数返回的时候，不就还在临界区了吗？
            //返回时：必须先参与锁的竞争，重新加上锁，函数才会返回！
            pthread_cond_wait(&_p_cond,&_mutex);
        }
        //1.没有满||2.被唤醒了
        _block_queue.push(in);//生产到阻塞队列
        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_c_cond);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_p_cond);
        pthread_cond_destroy(&_c_cond);
    }

private:
    std::queue<T> _block_queue;//临时资源
    int _max_cap;
    pthread_mutex_t _mutex;
    pthread_cond_t _p_cond;//生产者条件变量
    pthread_cond_t _c_cond;//消费者条件变量


    //int low_water
};
